MCU FreeRTOS下的串口编程

描述

刚接触FreeRTOS的时候,就对串口在FreeRTOS下如何应用的问题比较困惑,现在完成了一个小项目,
也有点心得,在这里记录一下使用方式,方便日后参考:

代码

串口中断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
void USART1_IRQHandler(void)    //User debug
{
portBASE_TYPE usart1_Que_Woken=pdFALSE;

if(USART_GetITStatus(USART1,USART_IT_TXE)!=RESET)
{
//USART_ClearITPendingBit(USART1,USART_IT_TXE);
if( xQueueReceiveFromISR( L0_TxQue, &DTS, &usart1_Que_Woken ) == pdTRUE )
{
/* A character was retrieved from the queue so can be sent to the
THR now. */

USART_SendData( USART1,DTS);
}
else
{
USART_ITConfig( USART1, USART_IT_TXE, DISABLE );
}
}
//如果TXE中断发生,从Tx队列中提取数据,并发送,直到提取数据完毕,关掉TXE中断。
//TXE中断被当做一个启动传输的标志,当有任务需要使用串口输出数据的时候,首先往队列中输入数据,然后打开TXE中断,这样串口中断处理程序就会进入TXE,读取队列并发送数据。



if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
{
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
L0_RxBuffer[L0_RxCount++]=USART_ReceiveData(USART1); //Save to L0 Buffer, Send to L1 every 20 bytes.
if(L0_RxCount>=20)
{
L0_RxCount=0;
xQueueSendToBackFromISR(L0_RxQue,L0_RxBuffer,&usart1_Que_Woken);
}
}

//如果RXNE中断发生,我这里先把收到的数据存入20byte的buffer,20byte存满之后,再一次性发送到接受队列,负责 //处理接收数据的任务,能够从队列中收取数据则运行,再把数据做处理,我们协议对顶20byte作为一个基础数据包 //所以我这里用20byte作处理。
portEND_SWITCHING_ISR(usart1_Que_Woken);

}

需要发送时:

1
2
3
4
5
6
for(Buffer_index=0;Buffer_index<20;Buffer_index++)
{
xQueueSendToBack(L0_TxQue,&L1_ACK_Buffer[Buffer_index],portMAX_DELAY);
USART_ITConfig( USART1, USART_IT_TXE,ENABLE ); //Give signal to usart handler to start a 2o bytes' data transfer
}
//我这里还是20个字节,做一次传输,for循环20次,把20byte数据传到串口发送队列,并使能RXNE中断,以通知中断处理。

需要接收时:

1
2
3
4
5
XSTATUS=xQueueReceive(L0_RxQue,L0_RxBuffer_Temp,portMAX_DELAY);
if(XSTATUS==pdPASS)
{
//接收任务收取队列,收取成功则做数据处理。
}

解释

由于项目比较简单,只有一个任务TX任务统一负责发送,RX任务负责接收,所以没有考虑 串口使用权 的问题。
FreeRTOS中有一段话:

有效使用队列:
FreeRTOS的大多数demo应用程序中都包含一个简单的UART驱动,其通过队 列将字符传递到发送中断例程,也使用队列将字符从接收中断例程中传递出来。
发送或 接收的每个字符都通过队列单独传递。这些UART驱动的这种实现方式只是单纯了为 了演示如何在中断中使用队列。
实际上利用队列传递单个字符是极其低效的,特别是在 波特率较高的时后,所以这种方式并不建议用在产品代码中。
实际应用中可以采用下述
更有效的方式:
1· 将接收到的字符先缓存到内存中。当接收到一个传输完成消息,或是检测到传输中 断后,使用信号量让某个任务解除阻塞,这个任务将对字符缓存进行处理。
2· 在中断服务中直接解析接收到的字符,然后通过队列将解析后经解码得到的命令发 送到处理任务(与图23中描述的方式类似)。
这种技术仅适用于数据流能够快速解析 的场合,这样整个数据解析工作才可以放在中断服务中完成

我们项目由于包含了数据包分包组包的协议,所以收的部分只能一个数据包20byte做一次上层处理了。

使用FreeRTOS不是很久,理解也比较浅薄,只是自己记录下来供日后参考,不对的地方恳请阅者指正。